<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8">
    <title>WebSql-AI智能助手</title>
    <link rel="shortcut icon" type="image/x-icon" th:href="@{/static/img/favicon.ico}" media="screen"/>
    <link rel="stylesheet" th:href="@{/static/css/layui.css}" media="all"/>
    <link rel="stylesheet" th:href="@{/static/css/aiPage.css}" media="all"/>
</head>
<body>
<div class="layui-container">
    <div class="copilot-container">
        <div class="copilot-header">
            <svg t="1762763574651" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
                 p-id="5532" width="48" height="48">
                <path d="M511.994264 511.994264m-511.994264 0a511.994264 511.994264 0 1 0 1023.988529 0 511.994264 511.994264 0 1 0-1023.988529 0Z"
                      fill="#28176D" p-id="5533"></path>
                <path d="M769.87841 652.183853h-53.444341V522.260992h53.444341zM789.528583 522.260992h-19.650173v129.922861h84.898383V522.260992h-65.24821z"
                      fill="#F8C642" p-id="5534"></path>
                <path d="M772.012054 782.095242h-55.577985V652.172382H772.012054z" fill="#F8C642" p-id="5535"></path>
                <path d="M842.777913 782.095242h-72.910974V652.183853h84.886912v117.923981a11.99888 11.99888 0 0 1-11.975938 11.987408z"
                      fill="#7B49B6" p-id="5536"></path>
                <path d="M836.571992 522.260992H716.434069V392.338132h120.137923z" fill="#FC3A64" p-id="5537"></path>
                <path d="M854.776793 522.260992h-65.24821V392.338132h65.24821z" fill="#FFFFFF" p-id="5538"></path>
                <path d="M348.518131 692.73456l-20.18932 88.95919H169.211736l126.951818-522.14628h224.124391l120.447646 522.157751H483.316253l-20.533455-88.959189z m28.047095-122.48952h58.170477l-28.735367-127.640091z"
                      fill="#F8C642" p-id="5539"></path>
                <path d="M296.163554 259.54747l-22.896524 94.190059H542.014406l-21.726461-94.190059H296.163554z"
                      fill="#7B49B6" p-id="5540"></path>
                <path d="M220.625674 570.24504h214.1215l28.047095 122.48952H190.846427l29.779247-122.48952z"
                      fill="#FC3A64" p-id="5541"></path>
                <path d="M406.000336 442.604949h156.513112l29.435111 127.640091H434.747174l-28.746838-127.640091z"
                      fill="#FFFFFF" p-id="5542"></path>
                <path d="M718.556241 241.893286h134.098379v47.61697H718.556241z" fill="#FC3A64" p-id="5543"></path>
                <path d="M718.556241 288.087826h134.098379v47.61697H718.556241z" fill="#FC3A64" p-id="5544"></path>
            </svg>
            <h3>AI Data Copilot</h3>
        </div>
        <div class="copilot-chat-area">
            <form class="layui-form">
                <div id="chat-history">
                </div>
                <div class="chat-input-container">
                    <div class="database-selector">
                        [[${database}]]
                        <input type="hidden" th:value="${database}" name="dataBaseName" id="dataBaseName"/>
                        <input type="hidden" th:value="${table}" name="tableName" id="tableName"/>
                        <i class="layui-icon layui-icon-addition"></i><a></a>
                    </div>
                    <div class="chat-input">
                        <textarea id="question" placeholder="请问我SQL语句相关问题..."></textarea>
                        <button type="button" lay-filter="query" id="query" lay-submit>
                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none"
                                 xmlns="http://www.w3.org/2000/svg">
                                <path d="M22 2L11 13" stroke="white" stroke-width="2" stroke-linecap="round"
                                      stroke-linejoin="round"/>
                                <path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="white" stroke-width="2"
                                      stroke-linecap="round"
                                      stroke-linejoin="round"/>
                            </svg>
                        </button>
                    </div>
                </div>
            </form>
        </div>
        <div class="copilot-footer">
            <p>请在使用前仔细查看输出内容</p>
            <p>所有内容均由人工智能模型生成,其生成内容的准确性和完整性无法保证,不代表我们的态度或观点</p>
        </div>
    </div>
</div>
<script th:src="@{/static/layui.js}"></script>
<script th:replace="~{base::ctx}"></script>
<script th:src="@{/static/lay-config.js}"></script>
<script th:src="@{/static/code/highlight.min.js}"></script>
<script th:src="@{/static/code/sql-formatter.min.cjs}"></script>
<script type="text/html" id="table-sql-code-tpl">
    <strong><i class="layui-icon layui-icon-bot"></i>Ai</strong>
    <br>
    <pre class="layui-code chat-text-sql{{- d.id}}">
    {{- d.data}}
    </pre>
</script>
<script>
    const SQL_KEYWORD = ['select', 'insert', 'update', 'delete', 'from', 'where', 'order by', 'limit', 'offset', 'create', 'drop', 'alter', 'truncate', 'rename', 'set', 'show', 'desc', 'explain', 'begin', 'commit', 'rollback', 'lock', 'unlock', 'grant', 'revoke', 'call', 'declare', 'procedure', 'function', 'trigger', 'view', 'index'];

    layui.use(['jquery', 'layer', 'form', 'code',], function () {
        const layer = layui.layer;
        const form = layui.form;
        const $ = layui.jquery;
        const code = layui.code;
        let codeInst;
        let indexEl = 0;


        // 矫正模型给的换行错误问题
        const keywordHtml = function (text, index) {
            if (text == null || text === '') {
                return text;
            }
            for (let i = 0; i < SQL_KEYWORD.length; i++) {
                const key = SQL_KEYWORD[i];
                const number = text.toLowerCase().trim().indexOf(key);
                if (number !== -1 && index === 0) {
                    return text.replace(new RegExp('\\b(' + key + ')\\b', 'gi'), '$1\n');
                }
                if (number !== -1 && index > 0) {
                    return text.replace(new RegExp('\\b(' + key + ')\\b', 'gi'), '\n $1 \n');
                }
            }
            return text;
        };

        //
        $('.suggestion-card').on('click', function () {
            const suggestionText = $(this).find('p').text();
            $('#question').val(suggestionText);
        });

        //新对话
        $('.layui-icon-addition').on('click', function () {
            post(ctx + "aiManager/clear", null, (res) => {
                document.getElementById('chat-history').innerHTML = '';
                recommend();
            });
        });

        //推荐查询
        $(document).on('click', '.recommendQuery', function () {
            const labelText = $(this).find('.recommend-item').text();
            $('#question').val(labelText);
            $("#query").trigger('click');
        });

        //推荐初始化
        function recommend() {
            post(ctx + "aiManager/queryRecommend", null, (res) => {
                if (res.code === 200) {
                    const data = res.data;
                    if (data!=null && data.length > 0) {
                        const history = document.getElementById('chat-history');
                        let container = '<div class="recommend-container"><div class="recommend-list">';
                        data.forEach(item => {
                            container += '<a class="recommendQuery" href="javascript:void(0);"><p class="chat-text recommend-item">' + item + '</p></a>';
                        });
                        container += '</div></div>';
                        history.innerHTML += container;
                    }
                }
            });
        }

        form.on('submit(query)', function (data) {

            const q = $('#question').val();
            if (!q) return layui.layer.msg('请输入问题');

            const answerDom = document.getElementById('chat-history');

            //关闭推荐
            const isFirstQuestion = answerDom.querySelector('.recommend-container') !== null;
            if (isFirstQuestion) {
                const recommendContainer = answerDom.querySelector('.recommend-container');
                if (recommendContainer) {
                    recommendContainer.remove();
                }
            }

            answerDom.innerHTML += '<p class="chat-text"><strong><i class="layui-icon layui-icon-username"></i></strong> ' + q + '</p>';
            answerDom.innerHTML += '<p class="chat-text"><strong><i class="layui-icon layui-icon-bot"></i></strong> 正在思考中...</p>';
            answerDom.scrollTop = answerDom.scrollHeight;

            $('#question').val("");
            const dataBaseName = document.getElementById('dataBaseName').value;
            const tableName = document.getElementById('tableName').value;

            let content = '/aiManager/stream?text=' + encodeURIComponent(q) + "&dataBaseName=" + dataBaseName + "&tableName=" + tableName;
            const source = new EventSource(content);
            let aiAnswer = '';
            let index = 0;
            indexEl++;

            source.onmessage = e => {
                aiAnswer += keywordHtml(e.data, index);
                index++;
                const aiMessages = answerDom.querySelectorAll('p > strong');
                const lastAiMessage = aiMessages[aiMessages.length - 1].parentElement;
                const head = "<strong><i class='layui-icon layui-icon-chat'></i>Ai</strong><br>";
                const content = "<pre class='layui-code chat-text-sql" + indexEl + "'>" + aiAnswer + "</pre>";
                lastAiMessage.innerHTML = head + content;
                settingCode(indexEl);
                answerDom.scrollTop = answerDom.scrollHeight;
            };
            source.onerror = function () {
                source.close();
                layui.layer.msg('回答完毕');
                answerDom.scrollTop = answerDom.scrollHeight;
            };
            return false;
        });


        const settingCode = function (indexEl) {
            codeInst = code({
                elem: '.chat-text-sql' + indexEl,
                highlighter: "hljs",
                encode: false,
                id: 'chat-text-sql' + indexEl,
                preview: true,
                layout: ['code'],
                tools: [
                    'copy',
                    'full',
                    {
                        title: ['执行SQL'],
                        type: 'link',
                        event: function (obj) {
                            if (window.parent) {
                                window.parent.postMessage({
                                    type: 'executeSQL',
                                    sql: obj.finalCode
                                }, '*');
                            }
                        }
                    }
                ]
            });
        };
        recommend();
    });
</script>
</body>
</html>